﻿using System;
using System.Globalization;

namespace Central.Linq {

	/// <summary>
	/// Класс определения фильтра
	/// </summary>
	public class FilterDefinition {
		#region конструктор

		public FilterDefinition()
			: this(Guid.NewGuid()) {
		}

		public FilterDefinition(string name, FilterOperator op, object value)
			: this(Guid.NewGuid(), name, op, value) {
		}

		/// <summary>
		/// Конструктор
		/// </summary>
		public FilterDefinition(Guid id) {
			this.Id = id;
		}

		/// <summary>
		/// Конструктор
		/// </summary>
		public FilterDefinition(Guid id, string name, FilterOperator op, object value)
			: this(id) {
			this.Name = name;
			this.Operator = op;
			this.Value = value;
		}

		#endregion конструктор

		/// <summary>
		/// Наименование параметра
		/// </summary>[DataMember]
		public string Name { get; set; }

		/// <summary>
		/// Оператор фильтрации
		/// </summary>[DataMember]
		public FilterOperator Operator { get; set; }

		/// <summary>
		/// Значение параметра
		/// </summary>
		public object Value { get; set; }

		///// <summary>
		///// Учитывается ли регистр букв
		///// </summary>
		//public bool IsCaseSensitive { get; set; }

		/// <summary>
		/// Уникальный идентификтор фильтра
		/// </summary>
		public Guid Id { get; set; }

		#region [+] cвойства

		/// <summary>
		/// возвращаемый предикат фильтров
		/// </summary>
		public string Predicate {
			get {
				return this.GeneratePredicate();
			}
		}

		#endregion [+] cвойства

		#region скрытые методы

		private string GeneratePredicate() {
			string operatorPredicate = "";
			switch (this.Operator) {
				case FilterOperator.Contains:
					operatorPredicate = "{0}.Contains([Value])";
					break;

				case FilterOperator.DoesNotContain:
					operatorPredicate = "Not {0}.Contains([Value])";
					break;

				case FilterOperator.StartsWith:
					operatorPredicate = "{0}.StartsWith([Value])";
					break;

				case FilterOperator.DoesNotStartsWith:
					operatorPredicate = "Not {0}.StartsWith([Value])";
					break;

				case FilterOperator.EndsWith:
					operatorPredicate = "{0}.EndsWith([Value])";
					break;

				case FilterOperator.DoesNotEndsWith:
					operatorPredicate = "Not {0}.EndsWith([Value])";
					break;

				case FilterOperator.IsNull:
					operatorPredicate = "{0}=null";
					break;

				case FilterOperator.IsNotNull:
					operatorPredicate = "{0}<>null";
					break;

				case FilterOperator.IsEqualTo:
					operatorPredicate = "{0}=[Value]";
					break;

				case FilterOperator.IsNotEqualTo:
					operatorPredicate = "{0}<>[Value]";
					break;

				case FilterOperator.IsGreaterThan:
					operatorPredicate = "{0}>[Value]";
					break;

				case FilterOperator.IsGreaterThanOrEqualTo:
					operatorPredicate = "{0}>=[Value]";
					break;

				case FilterOperator.IsLessThan:
					operatorPredicate = "{0}<[Value]";
					break;

				case FilterOperator.IsLessThanOrEqualTo:
					operatorPredicate = "{0}<=[Value]";
					break;
				default:
					break;
			}
			return System.String.Format(CultureInfo.CurrentCulture, operatorPredicate, this.Name);
		}

		#endregion скрытые методы

		#region методы

		/// <summary>
		/// сравнение объектов
		/// </summary>
		/// <returns></returns>
		public override bool Equals(object obj) {
			return Equals(obj as FilterDefinition);
		}

		/// <summary>
		/// сравнение объектов FilterDefinition
		/// </summary>
		/// <param name="other"></param>
		/// <returns></returns>
		public bool Equals(FilterDefinition other) {
			if (other == null)
				return false;

			return (other.Name.Equals(this.Name) && other.Operator.Equals(this.Operator) && ((other.Value == null && this.Value == null) || (other.Value != null && this.Value != null && other.Value.Equals(this.Value))));
		}

		/// <summary>
		/// получение Hash кода объекта FilterDefinition
		/// </summary>
		/// <returns></returns>
		public override int GetHashCode() {
			int hashFilterDefinitionName = this.Name.GetHashCode();

			int hashFilterDefinitionOperator = this.Operator.GetHashCode();

			int hashFilterDefinitionValue = 0;
			if (this.Value != null)
				hashFilterDefinitionValue = this.Value.GetHashCode();

			//Calculate the hash code
			return hashFilterDefinitionName ^ hashFilterDefinitionOperator ^ hashFilterDefinitionValue;
		}

		#endregion методы
	}
}